package com.edu.client;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.edu.pojo.*;
import com.edu.service.ExerciseService;
import com.edu.service.UserService;
import com.edu.util.ClearConsoleUtil;
import com.edu.util.JedisPoolUtil;
import com.edu.util.JsonUtil;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;

/**
 * @author five-five
 * @created 2021/11/26-16:35
 */
public class MainApp {
    private UserService userService = new UserService();
    private ExerciseService exerciseService = new ExerciseService();

    public static void main(String[] args) throws Exception {
        MainApp mainApp = new MainApp();
        mainApp.appStarter();
    }

    @Test
    public void appStarter() throws Exception {
        Scanner in = new Scanner(System.in);
        System.out.println("习题系统正在启动======================================");
        //注册或登录工作完成
        User curUser = doneLoginOrRegister(in);
        System.out.println(curUser.getName() + "登录成功");
        //添加清屏操作
        ClearConsoleUtil.doClearConsole(in);
        while (true) {
            System.out.println("请选择功能：1.生成试题，2.查看错题,3.限时考试，4.注销登录，-1:退出系统");
            int option = in.nextInt();
            if (option == 1) {
                //生成试题
                List<Exercise> exercises = generateExercises(in);
                //做题并保存在试卷
                Examination curExamination = doExercisesAndSaveToExamination(in, curUser, exercises);
                saveExercises(in, curUser, curExamination);
            } else if (option == 2) {
                //做错题
                doErrorProblems(in, curUser);
            } else if (option == 3) {
                //限时做题
                System.out.println("你选择了限时做题，请设置时长(单位:s)");
                int time = in.nextInt();
                //生成试卷
                List<Exercise> exercises = generateExercises(in);
                //做题并考试
                Examination curExamination = doExercisesAndSaveToExaminationDuringTime(in, curUser, exercises, time);
                //保存考试
                saveExercises(in, curUser, curExamination);
            } else if (option == 4) {
                System.out.println("注销完成。。。");
                appStarter();
                return;
            } else {
                System.out.println("===============================系统开始退出==========================");
                System.exit(0);
            }
        }
    }

    /**
     * 限时做题
     *
     * @param in
     * @param curUser
     * @param exercises
     * @param time
     * @return
     */
    private Examination doExercisesAndSaveToExaminationDuringTime(Scanner in, User curUser, List<Exercise> exercises, int time) {
        //添加清屏操作
        ClearConsoleUtil.doClearConsole(in);
        JedisPoolUtil.getJedisPoolInstance();
        System.out.println("开始计时");
        String timeKey = curUser.getName() + NormalKeys.TIMER_KEY;
        JedisPoolUtil.set(timeKey, "1");
        JedisPoolUtil.setOutTime(timeKey, time);
//        if (!JedisPoolUtil.exists(timeKey)) {
//            return curExamination;
//        }
        //保存在试卷
        Examination curExamination = new Examination();
        System.out.println("开始做题");
        List<ExerciseExt> exerciseExts = new ArrayList<>();
        int count = 0;
        curExamination.setUsername(curUser.getName());
        for (int i = 0; i < exercises.size(); i++) {
            Exercise curExercise = exercises.get(i);
            if (!JedisPoolUtil.exists(timeKey)) {
//                exerciseExts.add(exercises.subList(i,exercises.size()-1));
                List<ExerciseExt> exerciseExtList =
                        exercises.subList(i, exercises.size())
                                .stream()
                                .map(exercise -> new ExerciseExt(exercise.getLeft(), exercise.getRight(), exercise.getSymbol(), -1, false))
                                .collect(Collectors.toList());
                exerciseExts.addAll(exerciseExtList);
                count += exerciseExtList.size();
                break;
            }
            String str = "请输入该问题答案:\t";
            System.out.println(str + curExercise.fullString());
            int curResult = in.nextInt();
            //正确答案
            int result = 0;
            if (curExercise.getSymbol().equals("+")) {
                result = curExercise.getLeft() + curExercise.getRight();
            } else {
                result = curExercise.getLeft() - curExercise.getRight();
            }
            //统计错误率
            if (curResult != result) {
                count++;
            }
            ExerciseExt exerciseExt = new ExerciseExt(curExercise.getLeft(),
                    curExercise.getRight(),
                    curExercise.getSymbol(),
                    curResult,
                    curResult == result);
            exerciseExts.add(exerciseExt);
        }
        curExamination.setExerciseExts(exerciseExts);
        System.out.println("错误：" + count + "\t正确：" + (exercises.size() - count));
        System.out.println("=================时间已过===============");
        System.out.println("===========考试结束====================");
        return curExamination;
    }

    private void doErrorProblems(Scanner in, User curUser) {
        //添加清屏操作
        ClearConsoleUtil.doClearConsole(in);
        System.out.println("你选择了查看错题");
        //去redis中拿到试卷
        JedisPoolUtil.getJedisPoolInstance();
        String examinationNameSet = JedisPoolUtil.get(curUser.getName() + "_ExaminationNameSet");
        List<String> examinationNames = null;
        if (!StrUtil.isEmpty(examinationNameSet)) {
            examinationNames = JsonUtil.jsonToList(examinationNameSet, String.class);
            printExaminationNames(examinationNames);
            System.out.println("请选择一份试卷(,分割，下标从0开始！！！):");
            //不做长度判断
            int examinationIndex = in.nextInt();
            String curExaminationName = examinationNames.get(examinationIndex);
            System.out.println("你选择了" + curExaminationName);
            String key = curUser.getName() + "_" + curExaminationName + NormalKeys.USEREXAMINATIONPOST;
            String curExaminationJsonStr = JedisPoolUtil.get(key);
            Examination curExamination = JsonUtil.jsonToPojo(curExaminationJsonStr, Examination.class);
            List<ExerciseExt> exerciseExts = curExamination.getExerciseExts();
            //展示所有错题
            List<Exercise> exerciseList = exerciseExts.stream()
                    .filter(exerciseExt -> !exerciseExt.isCorrect())
                    .map(exerciseExt -> {
                        Exercise exercise = new Exercise(exerciseExt.getLeft(),
                                exerciseExt.getRight(), exerciseExt.getSymbol(), exerciseExt.getResult());
                        return exercise;
                    }).collect(Collectors.toList());
            if (exerciseList.size() == 0) {
                System.out.println("用户名：" + curUser.getName() + "的" + curExaminationName + "试卷下无错题记录");
            }
            Examination examination = doExercisesAndSaveToExamination(in, curUser, exerciseList);
            JedisPoolUtil.set(key, JsonUtil.objectToJson(examination));
        } else {
            System.out.println("该用户名下不存在错题");
        }


    }

    /**
     * 可拓展打印出错题试卷内容
     *
     * @param examinationNames examinationNames
     */
    private void printExaminationNames(List<String> examinationNames) {
        System.out.println(examinationNames);
    }


    private void saveExercises(Scanner in, User curUser, Examination curExamination) {
        boolean flag = false;
        while (!flag) {
            System.out.println("请输入试卷名：");
            String curExaminationName = in.next();
            JedisPoolUtil.getJedisPoolInstance();
            //判断试卷名是否重复
            String examinationNameSet = JedisPoolUtil.get(curUser.getName() + "_ExaminationNameSet");
            List<String> examinationNames = null;
            if (examinationNameSet == null) {
                examinationNames = new ArrayList<>();
            } else {
                examinationNames = JsonUtil.jsonToList(examinationNameSet, String.class);
            }
            if (!examinationNames.contains(curExaminationName)) {
                System.out.println("试题已保存至试卷：" + curExaminationName + "中");
                examinationNames.add(curExaminationName);
                JedisPoolUtil.set(curUser.getName() + "_ExaminationNameSet", JsonUtil.objectToJson(examinationNames));
                JedisPoolUtil.set(curUser.getName() + "_" + curExaminationName + NormalKeys.USEREXAMINATIONPOST, JsonUtil.objectToJson(curExamination));
                flag = true;
            } else {
                System.out.println("试卷名重复请重新输入");
            }
        }
    }

    private Examination doExercisesAndSaveToExamination(Scanner in, User curUser, List<Exercise> exercises) {
        //添加清屏操作
        ClearConsoleUtil.doClearConsole(in);
        //保存在试卷
        Examination curExamination = new Examination();
        if (!CollectionUtil.isEmpty(exercises)) {
            System.out.println("开始做题");
        }
        List<ExerciseExt> exerciseExts = new ArrayList<>();
        int count = 0;
        curExamination.setUsername(curUser.getName());
        for (int i = 0; i < exercises.size(); i++) {
            Exercise curExercise = exercises.get(i);
            String str = "请输入该问题答案:\t";
            System.out.println(str + curExercise.fullString());
            int curResult = in.nextInt();
            //正确答案
            int result = 0;
            if (curExercise.getSymbol().equals("+")) {
                result = curExercise.getLeft() + curExercise.getRight();
            } else {
                result = curExercise.getLeft() - curExercise.getRight();
            }
            //统计错误率
            if (curResult != result) {
                count++;
            }
            ExerciseExt exerciseExt = new ExerciseExt(curExercise.getLeft(),
                    curExercise.getRight(),
                    curExercise.getSymbol(),
                    curResult,
                    curResult == result);
            exerciseExts.add(exerciseExt);
        }
        curExamination.setExerciseExts(exerciseExts);
        System.out.println("错误：" + count + "\t正确：" + (exercises.size() - count));
        return curExamination;
    }

    private List<Exercise> generateExercises(Scanner in) {
        //添加清屏操作
        ClearConsoleUtil.doClearConsole(in);
        System.out.println("生成加试题或减试题还是混合试题。1.加试题，2.减试题，其他.混合试题");
        int exciseKinds = in.nextInt();
        System.out.println("请输入长度：0-50");
        int length = in.nextInt();
        List<Exercise> exercises = null;
        if (exciseKinds == 1) {
            exercises = exerciseService.generateAddFormula(length);
        } else if (exciseKinds == 2) {
            exercises = exerciseService.generateSubtractFormula(length);
        } else {
            exercises = exerciseService.generateBinaryFormula(length);
        }
        return exercises;
    }

    private User doneLoginOrRegister(Scanner in) {
        User result = null;
        boolean noRound = false;
        while (!noRound) {
            System.out.println("启动完成，请输入选项：1:登录\t其他:注册");
            int option = in.nextInt();
            System.out.println("启动完成，请输入用户名:");
            User user = new User();
            String userName = in.next();
            user.setName(userName);
            System.out.println("启动完成，请输入密码:");
            String userPwd = in.next();
            user.setPassword(userPwd);
            if (option == 1) {
                //根据用户名和密码去redis中查询
                noRound = userService.getUserByUserNameAndPwd(user);
                if (noRound) {
                    System.out.println("用户名为" + user.getName() + "登录成功");
                } else {
                    System.out.println("登录失败，请重新登录。。。。");
                }
            } else {
                //开始注册
                noRound = userService.addUserByUserNameAndPwd(user);
                if (noRound) {
                    System.out.println("用户名为" + user.getName() + "注册成功");
                }
            }
            if (noRound) {
                result = user;
            }
        }
        return result;
    }
}
